/*
 * Util
 * David li 090922
 */
if (!Util) {
    var Util = {};
}
/* firefox text-overflow ellipsis plugin */
jQuery.extend({
    isSupportTextoverflow:('textOverflow' in document.documentElement.style || 'OTextOverflow' in document.documentElement.style)
});
/*
 * autoUpdating: auto ellipsis element
 * childrenlevel 0:current element, >1: children element level, undefined: the finally children element
 */
(function($) {
    $.fn.ellipsis = function(autoUpdating,childrenlevel){
        //var s = document.documentElement.style;
		var autoUpdate=autoUpdating||false;
		var existLevel=typeof childrenlevel!='undefined';
        return this.each(function(){
            var el = $(this);
            if (el.css("overflow") == "hidden") {
				var aimDom = el;
				if (!existLevel || childrenlevel >= 0) {
					var level = 0;
					aimDom=el;
					while (aimDom.children().length > 0 && (!existLevel || level < childrenlevel)) {//get the direct wrap of text node 
						aimDom = aimDom.children();
						level++;
					}
				}
				aimDom = aimDom.eq(0);
                var originalText=aimDom.text();
				if(originalText.length==0){
					this.aimDom=null;// add by yuntao to fix  IE bug
                    //delete this.aimDom;
					return;
				}
				var originalHtml;
				if(autoUpdating) originalHtml=el.html();//backup for recover
                var w=aimDom.width();
                var t = aimDom.clone(true).css({'position':'absolute', 'width':'auto', 'overflow':'visible'}).hide();
				aimDom.after(t);
                var text = originalText;
                if (!jQuery.isSupportTextoverflow) {//if browser is FF
//                    if(!aimDom.data("bestpx")){//cache best pixel
//                       aimDom.data("bestpx",t.width());
//                    }
                    if (!aimDom.data("realvalue")) {
	                    aimDom.data("realvalue", originalText);
	                }
                    var temptext=aimDom.data("realvalue");
                    if(originalText.lastIndexOf("...")!=-1){
                        t.text(temptext);
                        text=temptext;
                    }else{
	                    if(originalText!=aimDom.data("realvalue")){//dom content have changed
	                        aimDom.data("realvalue",originalText);
	                        aimDom.data("bestpx",t.width());
	                    }
					}
//					if (t.width() != aimDom.data("bestpx")) {//word-bold
//                       aimDom.data("bestpx",t.width());
//                    }
//					if (aimDom.data("bestpx") > w) {
						var length=text.length;
						while (length > 0 && t.width() > w) {
							text = text.substr(0, --length);
							t.text(text + "...");
						}
//					}
                    aimDom.text(t.text());//change the text context to the ellipsis value
					aimDom.attr("title", aimDom.data("realvalue"));//add the title for the ellipsis node
                }else{
                    if(!aimDom.hasClass("qs-common-ellipsis")||originalText!=aimDom.data("realvalue")){
						aimDom.data("realvalue", originalText);
                        aimDom.addClass("qs-common-ellipsis");
						aimDom.attr("title",originalText);//add the title for the ellipsis node
                    }
                }
                t.remove();
                if (autoUpdate) {
                    var oldW = el.width();//auto refresh the text node 
                    setInterval(function(){
                        if (el.width() != oldW) {
                            oldW = el.width();
                            el.html(originalHtml);
                            el.ellipsis();
                        }
                    }, 200);
                }
            }
        });
    }
})(jQuery);

Util.FixIE = (function(){
    if (document.all) {
        document.execCommand("BackgroundImageCache", false, true);
    }
})();
/*
 * Util.DelayRun('resize', this._resizeBody, 10, this);
 * */
Util.DelayRun = function(timerKey, fn, delay, object){
    if (object.__DelayRunTimer) {
        if (object.__DelayRunTimer[timerKey]) {
            clearTimeout(object.__DelayRunTimer[timerKey]);
            object.__DelayRunTimer[timerKey] = -1;
        }
    }
    else {
        object.__DelayRunTimer = {};
    }
    object.__DelayRunTimer[timerKey] = setTimeout(function(){
        fn.call(object);
    }, delay);
};
Util.getScrollPosition=function(){
	if (typeof(window.pageYOffset) == 'number') {
	    this.getScrollPosition=function(){
            return {scrollx:window.pageXOffset,scrolly:window.pageYOffset};
		}
	}else if (document.documentElement && (typeof document.documentElement.scrollLeft!='undefined' || typeof document.documentElement.scrollTop!='undefined')) {
		this.getScrollPosition=function(){
			return {scrollx:document.documentElement.scrollLeft,scrolly:document.documentElement.scrollTop};
		}
	}else if (document.body && typeof document.body.scrollLeft!='undefined') {
		this.getScrollPosition=function(){
			return {scrollx:document.body.scrollLeft,scrolly:document.body.scrollTop};
		}
	}else{
		return {scrollx:0,scrolly:0};
	}
	return this.getScrollPosition();
}
//contains check f contains c
Util.contains = function(f, c){
    if (f == null) {
        return false;
    }
    var bCB2F = false;
    if (f.contains) {
        bCB2F = f.contains(c);
    }
    else {
        bCB2F = (f.compareDocumentPosition(c) == 20) ? true : false;
    }
    return bCB2F;
};

Util.addBetaTip = function(TextEl, TipEl){
    var el = (TextEl[0] || TextEl)
    el.innerHTML += ' (beta)';
    var timeout = null;
    var tipEl = $("<div class='wstl-options-tip'>This is a new feature that might have a few kinks to work out.</div>").appendTo(document.body);
    
    $(TipEl ? (TipEl[0] || TipEl) : el).bind('mouseover', function(e){
        var targetEl = $(e.target);
        var val = targetEl.parent().attr("value");
        if (timeout != null) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(function(){
            tipEl.show();
            tipEl.css({
                left: e.clientX + 10,
                top: e.clientY + 10
            });
        }, 100);
    }).bind('mouseout', function(){
        if (timeout != null) {
            clearTimeout(timeout);
        }
        tipEl.hide();
    });
};

//panel
Util.panel = function(callback){
    var html = '<div class="rtq-panel">' +
				'<div class="shadow"></div>' +
				'<div class="container">' +
				'<div class="hd"><h4>Title</h4><div class="hd-btn"><a class="close">X</a></div></div>' +
				'<div class="ctn"></div>' +
				'</div>' +				
				'</div>';
    this.jqDOM = $(html);
    this.title = null;
    this.ctn = null;
    this.utilType = "";
    this.closeCallback = callback;
    this._init();
    return this;
};
Util.panel.prototype = {
    _init: function(){
        var self = this;
        this.title = this.jqDOM.find('.hd h4');
        this.ctn = this.jqDOM.find('.ctn');
        this.jqDOM.find('.hd a.close').click(function(){
            self.hide();
            if (typeof self.closeCallback == 'function') {
                self.closeCallback();
            }
        });
        
        this.jqDOM.appendTo(document.body);
    },
    addToContent: function(obj){
        this.ctn.append(obj);
    },
    setTitle: function(str){
        this.title.html(str);
    },
    show: function(){
        this.jqDOM.find('.shadow').css({
            height: this.jqDOM.height()
        });
        this.jqDOM.show();
    },
    hide: function(){// type for utilmessage
        this.jqDOM.hide();
        if (this.utilType != "message") {
            QS_FullMarsk.hide();
        }
    },
    del: function(){
        this.jqDOM.remove();
    },
    setCloseCallback: function(callback){
        this.closeCallback = callback;
    }
};


Util.promptObj = null;
Util.prompt = function(msg, okCallback,config){
    if (!Util.promptObj) {
        var panel = new Util.panel();
        panel.jqDOM.addClass('rtq-prompt rtq-a-c-p');
        var content=(config&&config.label)?'<div class="qs-ui-label">'+config.label+':'+'</div>':"";
        panel.addToContent('<div class="qs-ui-content">'+content+'<input class="qs-ui-ipt name-ipt" type="text" /></div><div class="btn-ctn"><a href="javascript:void(0)" class="qs-ui-btn ok">OK</a><a class="qs-ui-btn cancel" href="javascript:void(0)">Cancel</a></div>');
        panel.setTitle('Confirm');
        panel.okCallback = function(val){
            
        };
        panel.config = {
            validateMethod: function(){
                return true;
            },
            cancelCallBack: null,
            beforeCloseCallBack: null
        }
        panel.input = panel.ctn.find('.name-ipt');
        var btnOK = panel.ctn.find('.ok');
        var btnCancel = panel.ctn.find('.cancel');
        
        var fnSubmit = function(){
            if (!panel.config.validateMethod(panel.input.val())) {
                return false;
            }
            if (typeof(panel.config.beforeCloseCallBack) == "function") {
                if (panel.config.beforeCloseCallBack(panel.input.val())) {
                    panel.hide();
                    panel.okCallback(panel.input.val());
                }
                else {
                    panel.input.val('');
                    panel.input.focus();
                }
            }
            else {
                panel.hide();
                panel.okCallback(panel.input.val());
            }
        };
        
        panel.input.bind('keydown', function(e){
            if (e.keyCode == 13) {
                fnSubmit();
            }
        });
        
        btnOK.click(fnSubmit);
        
        btnCancel.click(function(e){
            if (typeof(panel.config.cancelCallBack) == 'function') {
                panel.config.cancelCallBack();
            }
            panel.hide();
            return false;
        });
        
        Util.promptObj = panel;
        
    }
    
    Util.promptObj.okCallback = okCallback;
    if (config) {
        $.extend(true, Util.promptObj.config, config);
    }
    Util.promptObj.input.val('');
    Util.promptObj.setTitle(msg);
    Util.promptObj.show();
    Util.promptObj.input.focus();
};
//Util.prompt();
/*20120615 kidy refactor for fixing callback coverge bug*/
Util.confirmObj = null;
Util.confirm=function(){
    var cacheRquest={};
    var isLoading=false;
    var doNext=function(){
        for(var msg in cacheRquest){
            show(msg,cacheRquest[msg].callbacks[0],cacheRquest[msg]);
            return;
        }
    };
    var createConfirmObj=function(){
         var panel = new Util.panel();
            panel.jqDOM.addClass('rtq-confirm rtq-a-c-p');
            panel.addToContent('<h5>Message</h5><div class="btn-ctn"><input type="text" class="qs-ui-ipt" value="" /><a href="javascript:void(0)" class="qs-ui-btn ok">Ok</a><a class="qs-ui-btn cancel" href="javascript:void(0)">Cancel</a></div>');
            panel.setTitle('Confirm');
            panel.msg = panel.ctn.find('h5');
            panel.callback = function(){};
            var fnSubmit = function(){
                panel.hide();
                panel.callback(true);
                doNext();
            };
            //add by yuntao for change the text
            panel.setOkText = function(text){
                panel.ctn.find('.ok').text(text);
            };
            panel.setOkTip = function(text){
                panel.ctn.find('.ok')[0].title = text;
            };
            panel.setCancelText = function(text){
                panel.ctn.find('.cancel').text(text);
            };
            panel.setCancelTip = function(text){
                panel.ctn.find('.cancel')[0].title = text;
            };
            panel.ctn.find('.ok').click(fnSubmit);
            panel.ctn.find('.cancel').click(function(e){
                panel.hide();
                panel.callback(false);
                doNext();
            });
            panel.ctn.find('input').bind('keydown', function(e){
                if (e.keyCode == 13) {
                    fnSubmit();
                }
            });
            //panel.appendTo(document.body);
            Util.confirmObj = panel;
    };
    var show=function(msg,callback,config){ //config:{title:'Title'}
        if (!Util.confirmObj) {
            createConfirmObj();
        }
        if(!cacheRquest[msg]){
            cacheRquest[msg]={msg:msg,config:config,callbacks:[],closeCallbacks:[]};
            if(typeof callback=="function"){
                cacheRquest[msg].callbacks.push(callback);
            }
            if (config&&typeof config.closeCallback == 'function') {
                cacheRquest[msg].closeCallbacks.push(config.closeCallback);
            }
            if(!isLoading){
                Util.confirmObj.msg.html(msg);
                Util.confirmObj.msg.html(msg);
                Util.confirmObj.setTitle('Confirm');
                Util.confirmObj.setOkText('Ok');
                Util.confirmObj.setCancelText('Cancel');
                Util.confirmObj.setOkTip('');
                Util.confirmObj.setCancelTip('');
                if (config) {
                    if (config.title) {
                        Util.confirmObj.setTitle(config.title);
                    }
                    if (config.okText) {
                        Util.confirmObj.setOkText(config.okText);
                    }
                    if (config.cancelText) {
                        Util.confirmObj.setCancelText(config.cancelText);
                    }
                    if (config.okTipText) {
                        Util.confirmObj.setOkTip(config.okTipText);
                    }
                    if (config.cancelTipText) {
                        Util.confirmObj.setCancelTip(config.cancelTipText);
                    }
                    if (typeof config.closeCallback == 'function') {
                        with({message:msg}){
                            Util.confirmObj.setCloseCallback(function(){
                                while(cacheRquest[message].closeCallbacks.length>0){
                                    cacheRquest[message].closeCallbacks.shift()();
                                }
                                delete cacheRquest[message];
                                isLoading=false;
                                doNext();
                            });
                        }
                    }
                }
                if(typeof callback=="function"){
                    with({message:msg}){
                        Util.confirmObj.callback = function(b){
                            while(cacheRquest[message].callbacks.length>0){
                                cacheRquest[message].callbacks.shift()(b);
                            }
                            delete cacheRquest[message];
                            isLoading=false;
                        }
                    }
                }
                Util.confirmObj.show();
                Util.confirmObj.ctn.find('input').focus();
                isLoading=true;
            }
        }else{
            if(typeof callback=="function"){
                cacheRquest[msg].callbacks.push(callback);
            }
            if (config&&typeof config.closeCallback == 'function') {
                cacheRquest[msg].closeCallbacks.push(config.closeCallbacks);
            }
        }
    };
    return show;
}();
//Util.confirm();

Util.alertObj = null;
Util.alert = function(msg, config){ //config:{title:'Title'}
    if (!Util.alertObj) {
        var panel = new Util.panel();
        panel.jqDOM.addClass('rtq-alert rtq-a-c-p');
        panel.addToContent('<h5>Message</h5><div class="btn-ctn"><a href="javascript:void(0)" class="qs-ui-btn ok">OK</a></div>');
        panel.setTitle('Alert');
        panel.msg = panel.ctn.find('h5');
        
        var fnSubmit = function(){
            panel.hide();
            return;
        };
        
        panel.ctn.find('.ok').click(fnSubmit);
        
        panel.jqDOM.bind('keydown', function(e){
            if (e.keyCode == 13) {
                fnSubmit();
            }
        });
        Util.alertObj = panel;
    }
    Util.alertObj.msg.html(msg);
    if (config) {
        if (config.title) {
            Util.alertObj.setTitle(config.title);
        }
    }
    Util.alertObj.show();
};
//Util.alert();

Util.messageObj = null;
Util.message = function(msg){
    if (!Util.messageObj) {
        var panel = new Util.panel();
        panel.utilType = "message";
        panel.jqDOM.addClass('rtq-msg rtq-a-c-p');
        panel.addToContent('<h5>Message</h5>');
        panel.msg = panel.ctn.find('h5');
        var timer = null;
        
        panel.autoHide = function(dalay){
            if (timer) {
                clearTimeout(timer);
                timer = -1;
            }
            timer = setTimeout(function(){
                panel.hide();
            }, dalay || 8000);
        };
        
        panel.jqDOM.bind('keydown', function(e){
            if (e.keyCode == 13) {
                panel.hide();
            }
        });
        Util.messageObj = panel;
    }
    
    Util.messageObj.msg.html(msg);
    Util.messageObj.show();
    Util.messageObj.autoHide();
    
};
//Util.message();

/*
//DropDownList
Util.DropDownList1 = function(domEL, onChange, data, oConfig){
    this.dom = domEL[0] || domEL;
    this.mod;
    this.ipt;
    this.menu;
    this.data = data;
    this.cfg = {
        triggerByClick: false,
        animSlide: false,
        width: 80,
        disable: false,
        actionAtInit: true,
        syncListWidth: true,
        className: ''
    };
    $.extend(this.cfg, oConfig);
    this.selectedIndex = 0;
    this.onChange = onChange ||
    function(){
    };
    this.showTimer = -1;
    this.init();
};
Util.DropDownList1.CurrentMENU = null;
$(document.body).click(function(e){ // when click the document will hide the menu.
    if (Util.DropDownList1.CurrentMENU != null && !Util.contains(Util.DropDownList1.CurrentMENU.dom, e.target) && e.target != Util.DropDownList1.CurrentMENU.dom) {
        Util.DropDownList1.CurrentMENU.hideMenu();
    }
});
Util.DropDownList1.prototype = {
    init: function(){
        var self = this;
        //dom
        if ($(this.dom).hasClass('rtq-ddl')) {
            this.mod = $(this.dom);
            this.menu = this.mod.find('.rtq-ddl-menu');
            this.ipt = this.mod.children().eq(0).attr('readonly', 'readonly');
        }
        else 
            if (this.data) {
                //create DOM by data
                this.mod = $(document.createElement('div')).addClass('rtq-ddl');
                this.menu = $(document.createElement('ul')).addClass('rtq-ddl-menu');
                this.ipt = $('<div class="rtq-ddl-ipt"></div>').attr('readonly', 'readonly');
                this._bindData(this.data);
                $(this.dom).append(this.mod.append(this.ipt).append(this.menu));
            }
        this.mod.css({
            width: this.cfg.width
        }).addClass(this.cfg.className);
        this.ipt.css({
            width: this.cfg.width - 20
        });
        if (this.cfg.disable) {
            this.setDisable(true);
        }
        //event
        if(this.cfg.triggerByClick){
            this.mod.click(function(e){
                if (self.menu.css('overflow') == 'hidden') {
                    self.showMenu();
                }else {
                    self.hideMenu();
                }
            });
        }else{
            this.mod.mouseover(function(e){
                clearTimeout(self.showTimer);
                self.showTimer = setTimeout(function(){
                    //self.showMenu();
                    self.showMenu.call(self);
                }, 200);
            }).mouseout(function(e){
                clearTimeout(self.showTimer);
                self.showTimer = setTimeout(function(){
                    //self.hideMenu();
                    self.hideMenu.call(self);
                }, 200);
            });
        }
        //this.mod.hover(function(){self.mod.addClass('rtq-ddl-hover');},function(){self.mod.removeClass('rtq-ddl-hover');});
        
        this.menu.click(function(e){
            if (e.target.tagName.toLowerCase() == 'a') {
                self.selectedIndex = self.menu.children('li').index($(e.target).parent());
                self.menu.find('li a').removeClass('on');
                $(e.target).addClass('on');
                self._changeValue($(e.target).html(), $(e.target).attr('value'));
                self.hideMenu();
                return false;
            }
        });
        
        //$(document.body).click(function(e){
        //    if(!Util.contains(self.dom,e.target)&&e.target!=self.dom){
        //        self.hideMenu();
        //    }
        //});
        
        if (this.cfg.actionAtInit) {
            this.selectItemByIndex(this.selectedIndex);
        }
        else {
            this.setTextValue(null, this.menu.children('li').eq(this.selectedIndex).children('a').attr('value'));
        }
    },
    showMenu: function(){
        if (this.cfg.disable) {
            return;
        }
        if (Util.DropDownList1.CurrentMENU) {
            Util.DropDownList1.CurrentMENU.hideMenu();
        }
        //this.cfg.animSlide ? this.menu.slideDown('fast') : this.menu.show();
        if(this.cfg.animSlide){
            this.menu.slideDown('fast')
        }else{
            this.menu.removeClass('hideMenu');
        }
        this.mod.css({
            zIndex: 100
        });
        this.ipt.css({
            width: this.mod.width() - 20
        });
        var style = {
            zIndex: 9999,
            top: this.mod.height(),
            left: '-1px'
        };
        if (this.cfg.syncListWidth) {
            style.width = this.mod.width();
        }
        this.menu.css(style);
        Util.DropDownList1.CurrentMENU = this;
    },
    hideMenu: function(){
        if (this.menu != null) {
            //this.menu.hide();
            this.menu.addClass('hideMenu');
            this.mod.css({
                zIndex: 90
            });
        }
    },
    _changeValue: function(t, v){
        this.ipt.html(t.replace(/&gt;/g, '>').replace(/&lt;/g, '<'));
        this.ipt.attr('val', v);
        this.onChange(t, v);
    },
    _bindData: function(data){
        this.clearList();
        for (var i = 0, l = data.length; i < l; i++) {
            var val = typeof data[i].val == 'undefined' ? data[i].id : data[i].val;
            if(typeof(data[i].title)=="undefined"){
                this.menu.append('<li><a value="' + val + '" href="javascript:void(0)">' + data[i].txt + '</a></li>');
            }else{
                this.menu.append('<li><a value="' + val + '" href="javascript:void(0)" title="' + data[i].title + '">' + data[i].txt + '</a></li>');
            }
        }
    },
    getValue: function(){
        return this.ipt.attr('val') || '';
    },
    getText: function(){
        return this.ipt.html();
    },
    getSelectedIndex: function(){
        return this.selectedIndex;
    },
    clearList: function(){
        this.menu.html('');
    },
    rebindData: function(data){
        this._bindData(data);
    },
    insertItem: function(txt, val){
        this.menu.append('<li><a value="' + val + '" href="javascript:void(0)">' + txt + '</a></li>');
    },
    removeItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().remove();
    },
    selectItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').click();
    },
    selectItemByIndex: function(idx){
        this.menu.find('li a').eq(idx).click();
    },
    setTextValue: function(t, v){
        if (t) {
            this.ipt.html(t.replace(/&gt;/g, '>').replace(/&lt;/g, '<'));
        }
        if (typeof(v) != "undefined") {
            this.ipt.attr('val', v);
        }
        var el = this.menu.find('li a[value="' + v + '"]');
        if (el.length > 0) {
            this.ipt.html(el.html().replace(/&gt;/g, '>').replace(/&lt;/g, '<'));
            this.selectedIndex = this.menu.children('li').index(el.parent());
            this.menu.find('li a').removeClass('on');
            el.addClass('on');            
        }
        this.hideMenu();//updated by Wind 20110527
    },
    hideItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().hide();
    },
    showItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().show();
    },
    setDisable: function(b){
        this.cfg.disable = (typeof b == 'undefined') ? true : b;
        if (b) {
            this.mod.addClass('rtq-ddl-disable');
        }
        else {
            this.mod.removeClass('rtq-ddl-disable');
        }
    },
    clearUp: function(){
        //this.mod.remove();
        //this.dom = this.mod = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
    },
    resize: function(width){
        this.cfg.width = width;
        this.mod.css({
            width: this.cfg.width
        });
        this.ipt.css({
            width: this.cfg.width - 20
        });
    },
    clear: function(){ // 
        this.mod.unbind("click").unbind("mouseout").unbind("mouseover");
        this.menu.unbind("click");
        this.dom = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
        this.mod.remove();
        this.mod = null;
    }
};
*/
Util.DropDownList = function(domEL,onChange, data, oConfig,viewScope){
    this.dom = domEL[0] || domEL;
    this.data = data;
    this.cfg = {
        triggerByClick: false,
        animSlide: false,
        width: $(this.dom).width()||80,
        disable: false,
        actionAtInit: true,
        syncListWidth: true,
        className: '',
        showScrollbar:false,
		ellipsis:false
    };
    $.extend(this.cfg, oConfig);
    this.selectedIndex = 0;
	this.viewScope=viewScope||$(document.body);
    this.onChange = onChange ||function(){};
	this.bMenuHaveReversed=false;
    this.init();
};
Util.DropDownList.CurrentMENU = null;
$(document.body).click(function(e){ // when click the document will hide the menu.
    if (Util.DropDownList.CurrentMENU != null && !Util.contains(Util.DropDownList.CurrentMENU.dom, e.target) && e.target != Util.DropDownList.CurrentMENU.dom) {
        Util.DropDownList.CurrentMENU.hideMenu();
    }
});
Util.DropDownList.prototype = {
    init: function(){
        //create DOM by data
        this.mod = $(document.createElement('div')).addClass('rtq-ddl');
        this.menu = $(document.createElement('ul')).addClass('rtq-ddl-menu');
		this.menuScroll=$(document.createElement('div')).addClass('rtq-ddl-menuScroll').append(this.menu);
        this.menuWrap = $(document.createElement('div')).addClass('rtq-ddl-menuWrap').append(this.menuScroll);
        this.ipt = $('<div class="rtq-ddl-ipt"></div>').attr('readonly', 'readonly');
		if(this.cfg.ellipsis){
			this.menuWrap.addClass('qs-ddl-ellipsis');
			this.ipt.addClass('qs-common-ellipsis');
		}
        this._bindData(this.data);
        $(this.dom).append(this.mod.append(this.ipt).append(this.menuWrap));
        if (this.cfg.showScrollbar) {
            this.scrollpanel = new Util.ScrollPanel(this.menuScroll, {
                showY: true,
                showX: true,
                delayRun: false
            });
        }
        this.mod.css({
            width: this.cfg.width
        }).addClass(this.cfg.className);
        this.ipt.css({
            width: this.cfg.width - 20
        });
        if (this.cfg.disable) {
            this.setDisable(true);
        }
        this._bindEvent();
    },
    _bindEvent:function(){
        //event
        var self = this;
        if(this.cfg.triggerByClick){
            this.mod.bind("click.dropdown",function(e){
				if($(e.target).closest(".rtq-scrollbar").length != 0) return;
                if (self.menuWrap.css('overflow') == 'hidden') {
                    Util.DelayRun('ui_dropdownlist', self.showMenu, 100, self);
                }else {
                    Util.DelayRun('ui_dropdownlist', self.hideMenu, 100, self);
                }
            });
        }else{
            this.mod.bind("mouseover.dropdown",function(e){
                Util.DelayRun('ui_dropdownlist', self.showMenu, 200, self);
            }).bind("mouseout.dropdown",function(e){
                Util.DelayRun('ui_dropdownlist', self.hideMenu, 200, self);
            });
        }
        //this.mod.hover(function(){self.mod.addClass('rtq-ddl-hover');},function(){self.mod.removeClass('rtq-ddl-hover');});
        this.menuScroll.bind("click.dropdown",function(e){
			e.stopPropagation();
            var datael=[],el=$(e.target);
            if (el.closest(".rtq-scrollbar").length == 0&&e.target.tagName.toLowerCase() == 'a') {
                self.selectedIndex = self.menu.children('li').index(el.parent());//in all selectable
                var value=el.attr('value'),count=0;
                datael = self.menu.find("li a[value = '"+value+"']");
                for(var i=0,l=datael.length;i<l;i++){
                    if(datael.get(i)==e.target){
                        break;
                    }else{
                        count++
                    }
                }
                self.menu.find('li a').removeClass('on');
                el.addClass('on');
				
                self._changeValue(self._getTxtByValue(value), value,count);
                self.hideMenu();
            }
        });
        $(document.body).click(function(e){
            if(!Util.contains(self.dom,e.target)&&e.target!=self.dom){
                self.hideMenu();
            }
        });
        if (this.cfg.actionAtInit) {
            this.selectItemByIndex(this.selectedIndex);
        }
        else {
            this.setTextValue(null, this.menu.children('li').eq(this.selectedIndex).children('a').attr('value'));
        }
    },
    showMenu: function(){
        if (this.cfg.disable||!this.menuWrap.hasClass('hideMenu')) {
            return;
        }
        if (Util.DropDownList.CurrentMENU) {
            Util.DropDownList.CurrentMENU.hideMenu();
        }
		//this.cfg.animSlide ? this.menu.slideDown('fast') : this.menu.show();
        if(this.cfg.animSlide){
            this.menuWrap.slideDown('fast');
        }else{
            this.menuWrap.removeClass('hideMenu');
        }
        this.mod.css({
            zIndex: 100
        });
        var position=this._getPostion();
        var style = {
            zIndex: 9999,
            top:position.top,
            left:position.left
        };
        if (this.cfg.syncListWidth) {
            style.width = this.mod.width();
			this.cfg.width =style.width;
        }
        if(this.cfg.showScrollbar){
            this.scrollpanel.reSize(this.cfg.width,position.AvailHeight);
        }
        this.menuWrap.css(style);
        if (this.cfg.ellipsis) {//!jQuery.isSupportTextoverflow
            this.menu.find("li").ellipsis();
        }

        Util.DropDownList.CurrentMENU = this;
    },
	_ellipsis:function(w,h){
		if (this.cfg.ellipsis) {
            this.ipt.ellipsis(false);
        }
	},
    resize:function(w,h){
        var w=w||$(this.dom).width();
        this.cfg.width=w
		
        this.mod.css({
            "width": w
        });
        this.ipt.css({
            "width": w-20
        });
        if(typeof h!='undefined'){
            this.cfg.height=h;
        }
		this._ellipsis();
    },
    _menuReverse:function(aimDirection){
		if(aimDirection==this.bMenuHaveReversed) return;
	 	this.bMenuHaveReversed=aimDirection;
	 	$(this.menu.children().get().reverse()).appendTo(this.menu.empty());
    },
    _getPostion:function(){
        var iptHeight=this.mod.height();
        var modOffset=this.mod.offset();
		var scrollPosition=Util.getScrollPosition();
		var scopeoffset=this.viewScope.offset();
        var realmenuHeight=this.menu.height();
		var modTopHeight=modOffset.top-scrollPosition.scrolly-scopeoffset.top;
        var documentHeight=this.viewScope.height();//$(el).height() dont include padding, but offsetHeight do.
        var downAvailHeight=documentHeight - modTopHeight - iptHeight-12;
		var position={top: iptHeight,left: "-1px"};
		if(this.cfg.showScrollbar){
			//display down
			this._menuReverse(false);
			if(downAvailHeight >= realmenuHeight){
				position.showScroll=false;
				position.AvailHeight =realmenuHeight;
			}else{
				if (typeof this.cfg.height == 'undefined') {
					position.showScroll = true;
					position.AvailHeight = downAvailHeight;
				}
				else {
					position.showScroll = true;
					position.AvailHeight = Math.min(this.cfg.height, downAvailHeight);
				}
			}
		}else{
			if(downAvailHeight >= realmenuHeight){
				//display down
				this._menuReverse(false);
				position.showScroll=false;
				position.AvailHeight=downAvailHeight;
			}else if(modTopHeight >= realmenuHeight){
				//display up
				this._menuReverse(true);
				position.showScroll=false;
				position.AvailHeight =realmenuHeight;
	            position.top = -realmenuHeight;
			}else{
				//display auto adapted
				this._menuReverse(false);
	            position.showScroll=true;
	            position.AvailHeight=downAvailHeight;
			}
		}
		if(position.AvailHeight<30&&position.AvailHeight<realmenuHeight){//display area <40px
            //display up
            this._menuReverse(true);
            if (modTopHeight >= realmenuHeight) {
                position.showScroll = false;
                position.AvailHeight = realmenuHeight;
                position.top = -realmenuHeight;
            }else{
                //display auto adapted
                position.showScroll=true;
                position.AvailHeight=modTopHeight;
				position.top = -modTopHeight;
            }
        }
		return position;
    },
    hideMenu: function(){
        if (this.menu != null) {
            //this.menu.hide();
            this.menuWrap.addClass('hideMenu');
            this.mod.css({
                zIndex: 90
            });
        }
    },
    _changeValue: function(t, v,index){
        this.ipt.html(this._convertSpecialValue(t));
        this.ipt.attr('val', v);
        this.onChange(t, v, index);
		this._ellipsis();
    },
    _bindData: function(data){
        this.clearList();
		var nullIndex=[];
        for (var i = 0, l = data.length; i < l; i++) {
			if (data[i] == null) {
				nullIndex.push(i);
				continue;
			}
            var val =typeof data[i].val == 'undefined' ? data[i].id : data[i].val;
            var item=null;
            if (this.cfg.ellipsis) {//ellipsis
				if(typeof(data[i].title)=="undefined"){
					item=$('<li><a value="' + val + '" href="javascript:void(0)">' + data[i].txt + '</a></li>');
				}else{
					item=$('<li><a value="' + val + '" href="javascript:void(0)" title="' + data[i].title + '">' + data[i].txt + '</a></li>');
				}
            }else if(typeof(data[i].title)=="undefined"){
                item=$('<li><a value="' + val + '" href="javascript:void(0)">' + data[i].txt + '</a></li>');
            }else{
                item=$('<li><a value="' + val + '" href="javascript:void(0)" title="' + data[i].title + '">' + data[i].txt + '</a></li>');
            }
            this.menu.append(item);
        }
		for(var i=0,l=nullIndex.length;i<l;i++){// remove null in data
			data.splice(nullIndex[i],1);
		}
    },
	_getTxtByValue:function(value){
		var data;
		for (var i = 0, l = this.data.length; i < l; i++) {
			data = this.data[i];
			if (data.val == value) {
				return data.txt;
			}
		}
	},
    getValue: function(){
        return this.ipt.attr('val') || '';
    },
    getText: function(){
        return this.ipt.html();
    },
    getSelectedIndex: function(){
        return this.selectedIndex;
    },
    clearList: function(){
        this.menu.html('');
    },
    rebindData: function(data){
		this.data=data;
        this._bindData(this.data);
    },
    insertItem: function(txt, val){
        this.menu.append('<li><a value="' + val + '" href="javascript:void(0)">' + txt + '</a></li>');
		if(!this.bMenuHaveReversed){
			this.data.unshift({txt:txt,val:val});
		}else{
			this.data.push({txt:txt,val:val});
		}
    },
    removeItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().remove();
		for (var i = 0, l = this.data.length; i < l; i++) {
            data = this.data[i];
            if (data.val == value) {
				this.data.splice(i,1);
                return;
            }
        }
    },
    selectItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').click();
    },
    selectItemByIndex: function(idx){
        this.menu.find('li a').eq(idx).click();
    },
	_convertSpecialValue:function(t){
		return t.replace(/&gt;/g, '>').replace(/&lt;/g, '<');
	},
    setTextValue: function(t, v,index){
        if (t) {
            this.ipt.html(this._convertSpecialValue(t));
        }
        if (typeof(v) != "undefined") {
            this.ipt.attr('val', v);
        }
        var el = this.menu.find('li a[value="' + v + '"]');
        if (el.length > 0) {
            el=el.eq(index||0);
            this.ipt.html(this._convertSpecialValue(el.html()));
            this.selectedIndex = this.menu.children('li').index(el.parent());
            this.menu.find('li a').removeClass('on');
            el.addClass('on');            
        }
        this.hideMenu();//updated by Wind 20110527
        this._ellipsis();
    },
    hideItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().hide();
    },
    showItemByValue: function(val){
        this.menu.find('a[value="' + val + '"]').parent().show();
    },
    setDisable: function(b){
        this.cfg.disable = (typeof b == 'undefined') ? true : b;
        if (this.cfg.disable) {
            this.mod.addClass('rtq-ddl-disable');
        }
        else {
            this.mod.removeClass('rtq-ddl-disable');
        }
    },
    clearUp: function(){
        //this.mod.remove();
        //this.dom = this.mod = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
    },
    clear: function(){ // 
        this.mod.unbind("click").unbind("mouseout").unbind("mouseover");
        this.menu.unbind("click");
        this.dom = this.ipt = this.menu = this.data = this.cfg = this.onChange = this.ss = null;
        this.mod.remove();
        this.mod = null;
    }
};


// Range Slider Component
Util.Silder = function(container, _option){
    this.options = {
        min: 0,
        max: 100,
        values: [0, 10],
        disabled: false,
        widthOfHandle: 7
    };
    this.onchange = null;
    this.onchanged = null;
    this.element = $(container);
    this.handles;
    this.midHandle;
    this._keySliding = false;
    this._handleIndex = null;
    this._dragStart = false;
    this._lastValPercent;
    this.perHandleWidth = 1;
    this._clickOffset = {
        x: 0,
        y: 0,
        dx: 0
    }; // drag middle the inital positon of mouse.
    if (_option) {
        $.extend(this.options, _option);
    }
    this._init();
}
Util.Silder.prototype = {
    _init: function(){
        var self = this, o = this.options;
        this.element.addClass("rtq-slider");
        this.elementSize = {
            width: this.element.outerWidth(),
            height: this.element.outerHeight()
        };
        this.element.find('.rtq-slider-handle').remove();
        //this.elementOffset = this.element.offset();
        this.perHandleWidth = 100 * this.options.widthOfHandle / this.elementSize.width;
        this.element.append('<div class = "rtq-slider-handle"><a class="rtq-slider-left" href="javascript:void(0)"></a></div><div class="rtq-slider-mid"><a></a></div><div class = "rtq-slider-handle"><a class="rtq-slider-right" href="javascript:void(0)"></a></div>');
        this.handles = this.element.find(".rtq-slider-handle");
        this.handles.each(function(i){
            $(this).data("index.sliderHandle", i);
            $(this).mousedown(function(e){
                var elm = e.target.tagName.toLowerCase();
                if (elm == "a") {
                    self._handleIndex = $(e.target).parent().data("index.sliderHandle");
                    self._startDrag(e);
                }
            });
        });
        this.midHandle = this.element.find(".rtq-slider-mid");
        this.midHandle.find("a").mousedown(function(e){
            self._handleIndex = 2;
            self._clickOffset = self._getMousePostion(e);
            self._clickOffset.dx = 0;
            self._startDrag(e);
        });
        this._refreshValue();
    },
    _startDrag: function(e){
        e.preventDefault();
        this._dragStart = true;
        $(document).bind('mousemove', this, this._mouseDrag);
        $(document).bind('mouseup', this, this._mouseStop);
    },
    _mouseDrag: function(event){
        var self = event.data;
        if (!self._dragStart) {
            return false;
        }
        event.preventDefault();
        var position = self._getMousePostion(event);//{x: event.pageX, y: event.pageY };
        var pixelTotal = self.elementSize.width, pixelMouse, o = self.options;
        var valueTotal = o.max - o.min;
        if (self._handleIndex == 2) { // drag middle.
            var dx = position.x - self._clickOffset.x - self._clickOffset.dx;
            var dv = valueTotal * dx / pixelTotal;
            self._clickOffset.dx += dx;
            self._slide(event, self._handleIndex, dv.toFixed(2));
        }
        else {
            pixelMouse = position.x - self.element.offset().left;
            var percentMouse = (pixelMouse / pixelTotal);
            if (percentMouse > 1) 
                percentMouse = 1;
            if (percentMouse < 0) 
                percentMouse = 0;
            var valueMouse = percentMouse * valueTotal, normValue = o.min + valueMouse;
            self._slide(event, self._handleIndex, normValue.toFixed(2));
        }
        
    },
    _mouseStop: function(event){
        var self = event.data;
        $(document).unbind("mousemove", self._mouseDrag);
        $(document).unbind("mouseup", self._mouseStop);
        self._dragStart = false;
        self._stop(event, self._handleIndex);
        self._handleIndex = null;
    },
    _slide: function(event, index, val){
        var newVal = parseFloat(val);
        var o = this.options;
        var flag = false;
        if (o.values && o.values.length > 1) {
            if (index == 2) { // drag middle.
                var dx = newVal;
                if (o.values[0] + newVal < o.min || o.values[1] + newVal > o.max) {
                    return;
                }
                o.values[0] = o.values[0] + dx, o.values[1] = o.values[1] + dx;
                flag = dx != 0;
            }
            else {
                var otherVal = o.values[index == 1 ? 0 : 1];
                if ((o.values.length == 2) && ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))) {
                    newVal = otherVal;
                }
                flag = (newVal != o.values[index]);
                if (flag) {
                    o.values[index] = newVal;
                }
            }
            if (flag) {
                if (this.onchange) {
                    this.onchange(o.values);
                }
                this._refreshValue();
            }
        }
    },
    _stop: function(event, index){
        if (this.onchanged) {
            this.onchanged(this.options.values);
        }
    },
    _refreshValue: function(){
        var o = this.options, self = this;
        if (this.options.values && this.options.values.length) {
            var valPercent = [];
            for (var i = 0; i < 2; i++) {
                valPercent[i] = (o.values[i] - o.min) / (o.max - o.min) * 100;
                valPercent[i] = valPercent[i] > (100 - self.perHandleWidth) ? 100 - self.perHandleWidth : valPercent[i];
                valPercent[i] = valPercent[i] < self.perHandleWidth ? self.perHandleWidth : valPercent[i];
            }
            this.handles.each(function(i, j){
                if (i == 0) {
                    $(this).css({
                        width: valPercent[0] + '%'
                    });
                }
                if (i == 1) {
                    $(this).css({
                        left: valPercent[1] + '%',
                        width: (100 - valPercent[1]) + '%'
                    });
                }
            });
            this._lastValPercent = valPercent;
            this.midHandle.css({
                left: valPercent[0] + "%",
                width: valPercent[1] - valPercent[0] + "%"
            });
        }
    },
    _getMousePostion: function(e){
        var de = document.documentElement, b = document.body, pos = {};
        var sl = de && de.scrollLeft || b.scrollLeft || 0, sr = de && de.scrollTop || b.scrollTop || 0;
        if (e.pageX == null && e.clientX != null) { // IE
            pos.x = e.clientX + sl;
            pos.y = e.clientY + sr;
        }
        else {
            pos.x = e.pageX + sl;
            pos.y = e.pageY + sr;
        }
        return pos;
    },
    changeOutSize: function(w, h){
        this.elementSize = {
            width: w,
            height: h
        };
        this.perHandleWidth = 100 * this.options.widthOfHandle / this.elementSize.width;
        this._handleIndex = null;
    },
    setOption: function(op){
        $.extend(this.options, op);
        if (op.values) {
            this._refreshValue();
        }
    },
    clear: function(){
        this.handles.unbind("mousedown");
        this.midHandle.find("a").unbind("mousedown");
        this.handles.remove();
        this.handles = this.midHandle = this.options = this.onchange = this.onchanged = null;
        this.element.removeClass("rtq-slider").removeData("slider").unbind(".slider");
        this.element = null;
    }
};
//data: [{name:'Name',id:'123'}];
Util.GroupBox = function(container, data, oConfig, callbacks){
    this.container = container[0] || container;
    this.el;
    this.groups = {};
    this.data = data;
    this.cfg = {
        disable: false,
        width: '100%',
        groupBoxHeight: 100,
        animate: false,
        autoHeight: false,
        expendAll:false
    };
    $.extend(this.cfg, oConfig);
    this.cb = {};
    $.extend(this.cb, callbacks);
    this.currentGroup = null;
    this.selectedIndex = 0;
    this.html = '<div class="rtq-groupbox"></div>';
    this.init();
};
Util.GroupBox.prototype = {
    init: function(){
        var self = this;
        this.el = $(this.html).width(this.cfg.width);
        this.bindData(this.data);
        if (typeof self.cfg.defaultExpand != 'undefined' && self.cfg.defaultExpand != 'all') {
            setTimeout(function(){
                self.expand(self.cfg.defaultExpand);
            }, 0);
        }
        else if(self.cfg.defaultExpand == 'all'){
            setTimeout(function(){
                self.expand();
            }, 0);
       }else{//default expend the first group
           for(var g in this.groups){
               setTimeout(function(){
                    self.groups[g].expand();
               }, 0);
               break;
           }
       }
       this.el.appendTo(this.container);
    },
    bindData: function(dataArray){
        this.data = dataArray;
        for (var i = 0; i < dataArray.length; i++) {
            this.createGroup(dataArray[i]);
        }
    },
    expend:function(id){
        if (typeof id != 'undefined') {
            if (typeof this.groups[id] != 'undefined') {
                this.groups[id].expand();
            }
        }else{
            for (var g in this.groups) {
                this.groups[g].expand();
            }
        }
    },
    dexpand:function(expectid){
        if (typeof expectid != 'undefined') {
            for (var g in this.groups) {
                if (g != expectid) {
                    this.groups[g].dexpand();
                }
            }
        }else{
            for (var g in this.groups) {
                this.groups[g].dexpand();
            }
        }
    },
    createGroup: function(data){
        var self = this;
        var group = {};
        group.groupHeight = this.cfg.groupBoxHeight;
        $.extend(group, data);
        var hg = "";
        if (this.cfg.autoHeight == true) {
            hg = 'auto';
        }
        else {
            hg = this.cfg.groupBoxHeight + 'px';
        }
        group.el = $('<div class="rtq-groupbox-group"><h3 class="rtq-groupbox-group-hd">' + data.name + '</h3><div class="rtq-groupbox-group-bd" style="height:' + hg + '"></div></div>');
        group.hd = group.el.children('.rtq-groupbox-group-hd');
        group.bd = group.el.children('.rtq-groupbox-group-bd');
        group.bdHeight = null;
        group.expand = function(){
            if (self.currentGroup && self.currentGroup != group && !self.cfg.expendAll) {
                self.currentGroup.dexpand();
            }
            group.isShow = true;
            group.el.addClass('rtq-groupbox-group-open');
            self.currentGroup = group;
            if (self.cfg.animate) {
                if (!group.bdHeight) {
                    group.bdHeight = group.bd.height();
                }
                group.bd.css({
                    overflow: 'auto'
                });
                group.bd.height(0).animate({
                    height: self.cfg.autoHeight == true ? group.bdHeight : group.groupHeight
                });
            }
            else {
                group.bd.show();
            }
        };
        group.dexpand = function(){
            group.isShow = false;
            group.el.removeClass('rtq-groupbox-group-open');
            
            if (self.cfg.animate) {
                group.bd.css({
                    overflow: 'hidden'
                });
                group.bd.animate({
                    height: 0
                });
            }
            else {
                group.bd.hide();
            }
        };
        group.hd.click(function(){
            if (group.isShow) {
                group.dexpand();
            }
            else {
                group.expand();
            }
            if(self.cb.onClickHead){
                self.cb.onClickHead(self.groups[data.id]);
            }
        });
        this.groups[data.id] = group;
        this.el.append(group.el);
    },
    getGroup: function(id){
        for (var g in this.groups) {
            if (this.groups[g].id == id) {
                return this.groups[g];
            }
        }
        return null;
    },
    clear: function(){
        if (this.groups) {
            for (var g in this.groups) {
                this.groups[g].hd.unbind("click");
                this.groups[g].hd = this.groups[g].bd = this.groups[g].expand = this.groups[g].dexpand = this.groups[g].data = null;
                this.data = null;
                this.groups[g].el.remove();
                this.groups[g].el = null;
            }
        }
    }
};

//Radio button/Checkbox
Util.SelectButton = function(container, data, callbacks, config){
    this.container = container[0] ? container : $(container);
    this.el;
    this.data = data;
    this.txt = data.txt;
    this.val = data.val;
    this.title=data.title;
    this.isSelected = data.isSelected?data.isSelected:false;
    this.cb = {
        onClick: function(value, item){
        },
        afterSelect: function(value, item){
        },
        afterInverse: function(value, item){
        }
    };
    $.extend(this.cb, callbacks);
    this.cfg = {
        type: 'radio', //'checkbox'
        withGroup: false,
        disable: false
    };
    $.extend(this.cfg, config);
    this.className = this.cfg.type == 'radio' ? 'rtq-radio' : 'rtq-checkbox';
    this.html = '';
    this.init();
};
Util.SelectButton.prototype = {
    init: function(){
        var a = document.createElement('a');
        a.innerHTML = this.txt;
        a.className = this.className;
        if (this.title && this.title != '') {
            a.setAttribute('title',this.title);
        }else if(this.cfg.needTitle){
            a.setAttribute('title',this.txt);
        }
        var self = this;
        this.el = $(a).click(function(e){
            if (self.cfg.disable) {
                return;
            }
            if (!self.cfg.withGroup) {
                if (self.isSelected) {
                    self.inverse();
                }
                else {
                    self.select();
                }
            }
            self.cb.onClick(self.val, self);
        });
        if (this.cfg.disable) {
            this.disable(true);
        }
        if (this.isSelected){
            this.select();
        }
        this.container.append(a);
    },
    disable: function(isDiasble){
        this.cfg.disable = isDiasble === true ? true : false;
        if (this.cfg.disable) {
            this.el.addClass('rtq-btn-disable');
        }
        else {
            this.el.removeClass('rtq-btn-disable');
        }
    },
    select: function(){
        this.el.addClass(this.className + '-on');
        this.isSelected = true;
        this.cb.afterSelect(this.val, this);
    },
    inverse: function(){
        this.el.removeClass(this.className + '-on');
        this.isSelected = false;
        this.cb.afterInverse(this.val, this);
    },
    clear: function(){
        this.el.unbind("click");
        this.cfg.afterInverse = this.cfg.afterSelect = this.cfg.onClick = null;
        this.data = null;
        this.el.remove();
    }
};

Util.ButtonGroup = function(container, data, callbacks, config){
    this.container = container[0] ? container : $(container);
    this.el;
    this.data = data;
    this.btns = {};
    this.cb = {
        onClick: function(value, item){
        }
    };
    $.extend(this.cb, callbacks);
    this.cfg = {
        type: 'radio', //'checkbox'
        multiSelect: false,
        inverse: true,
        vertical: false,
        disable: false,
        needTitle:false,
        defaultSelected:[]
    };
    $.extend(this.cfg, config);
    this.cfg.multiSelect = this.cfg.type == 'checkbox' ? true : false;
    this.init();
};
Util.ButtonGroup.prototype = {
    init: function(){
        this.el = $('<div class="rtq-btngroup' + (this.cfg.vertical ? ' rtq-btngroup-v' : '') + '"></div>').appendTo(this.container);
        this.bindData(this.data);
        if (this.cfg.disable) {
            this.disable(true);
        }
    },
    bindData: function(data){
        var self = this;
        this.data = data;
        this.el.empty();
        this.btns = {};
        for (var i = 0; i < data.length; i++) {
            this.btns[data[i].val] = new Util.SelectButton(this.el, {
                txt: data[i].txt,
                val: data[i].val,
                isSelected:$.inArray(data[i].val,this.cfg.defaultSelected)!=-1?true:false,
                title:data[i].title
            }, {
                onClick: function(v, btn){
                    self._onClick(v, btn);
                }
            }, {
                type: this.cfg.type,
                withGroup: true,
                needTitle:this.cfg.needTitle
            });
            if (typeof(data[i].checked) != "undefined" && data[i].checked == true) {
                this.btns[data[i].val].select();
            }
        }
    },
    _onClick: function(v, btn){
        var isSelf = btn.isSelected;
        if (!this.cfg.multiSelect) {
            for (var k in this.btns) {
                this.btns[k].inverse();
            }
        }
        if (this.cfg.inverse) {
            if (isSelf) {
                btn.inverse();
            }
            else {
                btn.select();
            }
        }
        else {
            btn.select();
        }
        this.cb.onClick(v, btn);
    },
    disable: function(isDiasble){
        this.cfg.disable = isDiasble === true ? true : false;
        for (var k in this.btns) {
            this.btns[k].disable(this.cfg.disable);
        }
    },
    getValue: function(){
        var v = [];
        for (var k in this.btns) {
            if (this.btns[k].isSelected) {
                v.push(this.btns[k].val);
            }
        }
        return v;
    },
    clear: function(){
        if (this.btns) {
            for (var o in this.btns) {
                if (typeof(this.btns[o].clear) == "function") {
                    this.btns[o].clear();
                }
            }
        }
        this.el = null, this.data = null;
    }
};
Util.CascadeMenu = function(_container, _option, _data, _callbacks){
    this.option = {
        display: true,
        isTraceMouse: false, // if right menu need trace mouse.
        autoHide: false, // when mouse out of menu, hide the menu
        menuContainment: "document", // "document", "window" or "Dom container"
        fixedDirection: true //  
    };
    this._menuOffset = {
        left: 0,
        top: 0
    }; // the offset to body
    this._ulSize = []; // the width for sub menu.
    this._itemDirection = []; // the show direction of sub menu.  0:left, right;     
    this.data = _data;
    this.menu;
    this.container = _container;
    this.menuContainment = [];
    this.menuItems = {};
    this.callbacks = {
        onHide: null,
        onClick: null
    }
    $.extend(this.callbacks, _callbacks);
    this._timeOut = null;
    $.extend(true, this.option, _option)
    this._init();
};
Util.CascadeMenu.currentMenu = null;
Util.CascadeMenu.prototype = {
    _init: function(isRebindData){
        this.menuItems = {};
        if (this.menu) {
            this.menu.remove();
            this.menu = null;
        }
        this.menu = this._createMenuItems(this.container, this.data, 0, "", null) || $('<ul class="rtq-menu-ul"></ul>').appendTo(this.container);// create the cascade menu UI.
        this.menu.addClass("rtq-menu").hide();
        var self = this;
        this._itemBindEvent(this.menu, this);
        this.menu.unbind("click.cascadeMenu").bind("click.cascadeMenu", this, this.menuOnClick).bind("mouseover.cascadeMenu", function(e){
            self.show();
            if (self._timeOut) {
                clearTimeout(self._timeOut)
            }
        });
        if (this.option.autoHide) {
            this.menu.unbind("mouseout.cascadeMenu").bind("mouseout.cascadeMenu", function(e){
                if (self._timeOut) {
                    clearTimeout(self._timeOut)
                }
                self._timeOut = setTimeout(function(){
                    self.hide();
                }, 300);
            });
        }
        
        $(window).resize(function(){
            self._setDragContainment();
        });
        
        if (!this.option.display && !isRebindData) {
            this.hide();
        }
        else {
            this._menuOffset = this.menu.offset();
        }
        this._setDragContainment();
    },
    _itemBindEvent: function(obj, self){
        var sf = this;
        obj.find(".rtq-menu-item").bind("mouseenter", this, function(e){
            var sf = e.data;
            var el = $(this); // bind the hover event to the menu item.
            el.addClass("rtq-menu-hover"); // right direction.
            var idx = el.attr("index");
            var tip = sf.menuItems[idx].data.tip;
            if (typeof(tip) != "undefined") {
                var tipEl = sf.container.find(".cascademenu-tip");
                if (tipEl.length > 0) {
                    tipEl.show();
                }
                else {
                    sf.container.append("<div class='cascademenu-tip'>" + tip + "</div>");
                    tipEl = sf.container.find(".cascademenu-tip");
                    tipEl.show();
                }
                tipEl.html(tip);
                tipEl.css({
                    top: el.position().top + 23,
                    left: el.parent().position().left + el.width()
                });
            }
            if (!self.option.fixedDirection) { // need to set direction
                var layer = el.parent().data("layer.CascadeMenu");
                var ulEl = el.find(">.rtq-menu-ul");
                if (ulEl.length) { // has sub menu.
                    self._ulSize[layer + 1] = {
                        width: ulEl.width(),
                        height: ulEl.height()
                    };
                    var d = self._setDirection(layer + 1, el.offset().top), h, v;
                    if (d.horizontal) {
                        h = "100%";
                    }
                    else {
                        h = (-self._ulSize[layer + 1].width);
                    }
                    if (d.vertical) {
                        v = 0;
                    }
                    else {
                        v = (-self._ulSize[layer + 1].height + 15); // down 20 px.
                    }
                    if (d.drag) {
                        v = v + d.drag;
                    }
                    ulEl.css({
                        left: h,
                        top: v
                    });
                }
            }
            else {
                var ulEl = el.find(">.rtq-menu-ul");
                if (ulEl.css("top") != 0 || ulEl.css("top") != '0px') {
                    ulEl.css("top", '0px')
                }
                if (ulEl.size() == 0) {
                    var ulEl = el;
                }
                var offsetTop = ulEl.offset().top;
                var height = ulEl.height();
                var limit = sf.menuContainment[1] + sf.menuContainment[3];
                if (offsetTop + height > limit) {
                    if (height > limit) {
                        ulEl.css({
                            top: -offsetTop
                        });
                    }
                    else {
                        ulEl.css({
                            top: limit - (offsetTop + height)
                        });
                    }
                }
            }
        }).bind("mouseleave", this, function(e){
            $(this).removeClass("rtq-menu-hover");
            if (typeof(e.data.container.find) == "function") {
                e.data.container.find(".cascademenu-tip").hide();
            }
        });
    },
    _getDataObj: function(sq, index){// 12345...
        if (typeof(sq) == "undefined" || sq == null) 
            return null;
        var data = null, indx;
        for (var i = 0; i <= sq; i++) {
            indx = parseInt(index[i]);
            if (i == 0) 
                data = this.data[indx];
            else 
                data = data.subMenu[indx];
        }
        return data;
    },
    reBindSecondLevelMenu: function(val, data, sq){
        var item = this.getItemByVal(val);
        if(!item.el.hasClass("rtq-menu-arrow")){
            item.el.addClass("rtq-menu-arrow")
        }
        item.el.find(".rtq-menu-ul").remove();
        this._createMenuItems(item.el, data, sq, item.el.attr("index"), item);
        this._itemBindEvent(item.el, this);
    },
    _createMenuItems: function(container, data, sq, inds, parent){ // sq is series index.
        var str = "", cls = "", cls2 = "", ind = inds, ty, $ul, preCls = "";
        if (data == null) 
            return;
        if (data.length) {
            $ul = $('<ul class ="rtq-menu-ul"></ul>').appendTo(container).data("layer.CascadeMenu", sq);
            for (var i = 0; i < data.length; i++) {
                if (!data[i]) {
                    continue;
                }
                if (data[i].display == false) {
                    continue;
                }
                preCls = typeof(data[i]["className"]) != "undefined" ? data[i]["className"] : ""; // custome class.
                ind = inds + "_" + i;
                this.menuItems[ind] = {};
                this.menuItems[ind]["data"] = this._copyItemData(data[i]);
                this.menuItems[ind]["parent"] = parent;
                this.menuItems[ind]["el"] = $('<li index=' + ind + ' class="rtq-menu-item ' + preCls + ((data[i].subMenu && data[i].subMenu.length) ? ' rtq-menu-arrow' : '') + (data[i].disable ? ' disable' : '') + '"></li>').appendTo($ul);
                if (typeof(data[i].renderer) == "function") {
                    data[i].renderer(this.menuItems[ind]["el"]);
                }
                else 
                    if (data[i].type == "separator") {
                        this.menuItems[ind]["el"].append('<div class="rtq-menu-separator"></div>');
                    }
                    else {
                        cls2 = "rtq-menu-a";
                        if (data[i].type == "checkbox") {
                            cls = 'class = "' + (data[i].checked ? 'rtq-chkbox ' : 'rtq-chkbox rtq-chkbox-off ') + cls2 + '"';
                        }
                        else if (data[i].type == "ratio") {
                            cls = 'class = "rtq-ratio rtq-ratio-off ' + cls2 + '"';
                        }else if (data[i].type == "switch") {
                            if (data[i].txt == data[i].sTxt[0]) {
                                cls = 'class = "on ' + cls2 + '"';
                            }
                            else {
                                cls = 'class = "' + cls2 + '"';
                            }
                        }else {
                            cls = 'class = "' + cls2 + '"';
                        }
                        ty = data[i].type ? data[i].type : "&nbsp;";
                        str = '<a ' + cls + 'type=' + ty + ' sq=' + sq + ' >' + data[i].txt + '</a>';
                        this.menuItems[ind]["el"].append(str);
                    }
                if (data[i].subMenu && data[i].subMenu.length) {
                    this._createMenuItems(this.menuItems[ind]["el"], data[i].subMenu, sq + 1, ind, this.menuItems[ind]);
                }
                if (typeof(data[i].selected) != "undefined" && data[i].selected == true){
                    this.menuItems[ind]["el"].children().removeClass("rtq-ratio-off");
                }
                if (data[i].disable === true) {
                    this.menuItems[ind]._isDisable = true;
                }
            }
        }
        return $ul;
    },
    _copyItemData: function(data){
        var d = {};
        for (var o in data) {
            if (o != "subMenu") {
                d[o] = data[o];
            }
        }
        return d;
    },
    _getPostion: function(e, $container){
        var scrollPosition=Util.getScrollPosition();
        var oSet = $container.offset();
        return {
            left: e.pageX + scrollPosition.scrollx - oSet.left,
            top: e.pageY + scrollPosition.scrolly - oSet.top
        };
    },
    setPosition: function(_left, _top){
        this.menu.css({
            top: _top,
            left: _left
        });
    },
    _selectMenuItem: function(item, flag){
        var ty = item.data.type, t = item.el.find(">a"), hl = item.data.autoHighlight;
        /*if (typeof(hl) != "undefined" && hl) {
            if (t.hasClass("rtq-ratio-off")) { /// not selcted
                t.removeClass("rtq-ratio-off");
            }else if (!item.el.hasClass("rtq-menu-on")) {
                item.el.addClass("rtq-menu-on");
            }
        }*/
        if (ty == "ratio") {
            if (!flag) {  // uncheck
                t.addClass("rtq-ratio-off");
            }else {  // check
                //t.closest("ul", this.menu).find(">li a").addClass("rtq-ratio-off");  // uncheck all the 
                if (t.hasClass("rtq-ratio-off")) { /// not selcted
                    t.closest("ul", this.menu).find(">li>a").addClass("rtq-ratio-off");
                    t.removeClass("rtq-ratio-off");
                } else if (item.el.hasClass("rtq-menu-on")) {
                    t.closest("ul", this.menu).find(">li").removeClass("rtq-menu-on");
                }
            }
        }else if (ty == "checkbox") {
            if (flag) {
                t.removeClass("rtq-chkbox-off");
            }else {
                t.addClass("rtq-chkbox-off");
            }
            item.checked = flag;
        }else if (ty == "switch") {
            if (flag) {
                t.addClass("on");
            }else {
                t.removeClass("on");
            }
            var inx = flag ? 0 : 1;
            t.html(item.data.sTxt[inx]);
            item["switch"] = flag ? "on" : "off";
        }
    },
    menuOnClick: function(e){
        var self = e.data;
        var flag = true;
        var t = $(e.target).closest(".rtq-menu-item", self.menu);
        var index = t.attr("index");
        if (typeof(index) == "undefined") 
            return false;
        var item = self.menuItems[index];
        if (item._isDisable === true) 
            return false;
        if (item.data && (typeof(item.data.selectable) == "undefined" || item.data.selectable)) { // if not define selectable its default value is true.
            if (item.data.type == "checkbox") {
                flag = t.find("a").hasClass("rtq-chkbox-off"); // not checked.
            }
            else 
                if (item.data.type == "switch") {
                    flag = !t.find("a").hasClass("on");
                }
            self._selectMenuItem(item, flag);
            if (typeof(self.callbacks.onClick == "function")) {
                self.callbacks.onClick(item);
            }
        }
    },
    show: function(e){
        if (Util.CascadeMenu.currentMenu != null && Util.CascadeMenu.currentMenu != this) {
            Util.CascadeMenu.currentMenu.hide();
        }
        var marg = 0, pos;
        if (typeof(this._ulSize[0]) == "undefined") 
            this._ulSize[0] = {
                width: this.menu.width(),
                height: this.menu.height()
            };
        if (this.option.isTraceMouse && typeof(e) != "undefined") {
            this._menuOffset = {
                left: e.pageX,
                top: e.pageY
            };
            pos = this._getPostion(e, this.container);
            this._setDragContainment();
            var direction = this._setDirection(0, pos.top);//this._itemDirection[layer] = {horizontal:h,vertical:v};
            if (!direction.horizontal) {// left
                pos.left = pos.left - this._ulSize[0].width
            }
            if (!direction.vertical) {
                pos.top = pos.top - this._ulSize[0].height;
            }
            if (direction.drag) {
                pos.top = pos.top + direction.drag;
            }
            this.menu.css(pos).show();
            this._itemDirection[0] = {
                horizontal: 1,
                vertical: 1
            }; // left and down.
            this._menuOffset = this.menu.offset();
        }
        else {
            this.menu.show();
        }
        Util.CascadeMenu.currentMenu = this;
        clearTimeout(this._timeOut); //david
    },
    hide: function(){
        this.menu.hide();
        if (this.callbacks.onHide) {
            this.callbacks.onHide();
        }
    },
    getDisplayState: function(){
        return this.menu.css("display") != "none";
    },
    getItemByVal: function(val, parentVal){
        var d, p;
        for (var o in this.menuItems) {
            d = this.menuItems[o].data;
            p = this.menuItems[o].parent == null ? null : this.menuItems[o].parent.data;
            if (val == d.val && (typeof(parentVal) == "undefined" || parentVal == null || (p != null && parentVal == p.val))) { // find the menuItem
                return this.menuItems[o];
            }
        }
        return null;
    },
    changeUIState: function(val, parentVal, flag){ // only change the UI state not excute callback.
        var item = this.getItemByVal(val, parentVal);
        if (item) {
            this._selectMenuItem(item, flag);
        }
    },
    disableItem: function(val, parentVal){
        var item = this.getItemByVal(val, parentVal);
        if (item&&!item._isDisable) {
            item._isDisable = true;
            item.el.addClass('disable');
        }
    },
    enableItem: function(val, parentVal){
        var item = this.getItemByVal(val, parentVal);
        if (item&&item._isDisable) {
            item._isDisable = false;
            item.el.removeClass('disable');
        }
    },
    changeItemClass: function(val, parentVal, className, flag, isChild){ // remove or add a class name to menu item.
        var d, p;
        if (typeof(isChild) == "undefined") {
            isChild = false;
        }
        for (var o in this.menuItems) {
            d = this.menuItems[o].data;
            p = this.menuItems[o].parent == null ? null : this.menuItems[o].parent.data;
            if (val == d.val && (typeof(parentVal) == "undefined" || parentVal == null || (p != null && parentVal == p.val))) { // find the menuItem
                if (isChild) {
                    if (flag) {
                        this.menuItems[o].el.find(">a").addClass(className)
                    }
                    else {
                        this.menuItems[o].el.parent().find("li a").addClass(className);
                        this.menuItems[o].el.find(">a").removeClass(className);
                    }
                }
                else {
                    flag ? this.menuItems[o].el.addClass(className) : this.menuItems[o].el.removeClass(className);
                }
                
            }
        }
    },
    reBind: function(data, flag){
        this.data = data;
        this._init(flag);
    },
    _setDragContainment: function(){ // set the menu containment
        var o = this.option;
        if (o.menuContainment == 'document' || o.menuContainment == 'window') {
            this.menuContainment = [0, 0, $(o.menuContainment == 'document' ? document : window).width(), $(document.body.parentNode).height()];
        }
        if (!(/^(document|window)$/).test(o.menuContainment) && o.menuContainment.constructor != Array) { // Dom element
            var ce = $(o.menuContainment)[0];
            if (!ce) 
                return;
            var co = $(o.menuContainment).offset();
            var over = ($(ce).css("overflow") != 'hidden');
            
            this.menuContainment = [(parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0), (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0), (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0), (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0)];
        }
        else 
            if (o.menuContainment.constructor == Array) {
                this.menuContainment = o.menuContainment;
            }
        
    },
    _setDirection: function(layer, offsetTop){
        if (layer < 0 || typeof(layer) == "undefined" || this._itemDirection.length < layer) 
            return 1;
        var preW = 0, preH = 0, h, v, drag = 0;
        for (var i = 0; i < layer; i++) {
            if (this._itemDirection[i].horizontal == 1) 
                preW += this._ulSize[i].width;
            else 
                preW -= this._ulSize[i].width;
            if (this._itemDirection[i].vertical == 1) 
                preH += this._ulSize[i].height;
            else 
                preH -= this._ulSize[i].height;
        }
        if (this._menuOffset.left + preW + this._ulSize[layer].width > (this.menuContainment[0] + this.menuContainment[2])) {
            h = 0; // left;
        }
        else {
            h = 1; //right
        }
        if (offsetTop + this._ulSize[layer].height > (this.menuContainment[1] + this.menuContainment[3])) {
            v = 0;//up
            if (offsetTop < this._ulSize[layer].height - (offsetTop == 0 ? 0 : 15) &&
            (this.menuContainment[1] + this.menuContainment[3]) > this._ulSize[layer].height) {// menu is higher the offsetTop
                v = 1;//down
                drag = (this.menuContainment[1] + this.menuContainment[3]) - (offsetTop + this._ulSize[layer].height);
            }
            else 
                if (offsetTop < this._ulSize[layer].height - (offsetTop == 0 ? 0 : 15)) {
                    drag = this._ulSize[layer].height - (offsetTop);
                }
        }
        else {
            v = 1; //down
        }
        this._itemDirection[layer] = {
            horizontal: h,
            vertical: v,
            drag: drag
        };
        return this._itemDirection[layer];
    },
    clear: function(){
        this.menu.unbind(".cascadeMenu");
        this.menu.find(".rtq-menu-item").unbind();
        for (var o in this.menuItems) {
            this.menuItems[o].parent = null;
            this.menuItems[o].el = null;
            this.menuItems[o].data = null;
        }
        this.data = null;
        this.menuItems = null;
        this.menu.remove();
    }
};

/*Custom confirm with radioButton group,depends on Util.ButtonGroup */
Util.customConfirmObj = null;
Util.customConfirm = function(msg, callback, config){
    if (!Util.customConfirmObj) {
        var panel = new Util.panel();
        panel.jqDOM.addClass('rtq-customConfirm rtq-a-c-p');
        panel.addToContent('<h5>Message</h5><div class="radio-container"></div><div class="btn-ctn"><a href="javascript:void(0)" class="qs-ui-btn ok">OK</a></div>');
        panel.setTitle('<br/>');
        panel.msg = panel.ctn.find('h5');
        panel.callback = function(){
        };
        panel.radioBtn = new Util.ButtonGroup(panel.ctn.find('.radio-container'), [{
            txt: 'Yes',
            val: 'yes',
            selected: true
        }, {
            txt: 'No',
            val: 'no'
        }], {
            onClick: function(v){
            
            }
        }, {
            vertical: true
        });
        panel.autoSelect = function(data){
            for (var i = 0, l = data.length; i < l; i++) {
                if (data[i].selected) {
                    panel.radioBtn.btns[data[i].val].select();
                    break;
                }
            }
        };
        panel.autoSelect(panel.radioBtn.data);
        var fnSubmit = function(){
            panel.hide();
            panel.callback(panel.radioBtn.getValue());
        };
        panel.ctn.find('.ok').click(fnSubmit);
        
        panel.jqDOM.bind('keydown', function(e){
            if (e.keyCode == 13) {
                fnSubmit();
            }
        });
        Util.customConfirmObj = panel;
    }
    
    Util.customConfirmObj.callback = callback ||
    function(){
    };
    Util.customConfirmObj.msg.html(msg);
    if (config) {
        if (config.title) {
            Util.customConfirmObj.setTitle(config.title);
        }
        if (config.radioData) {
            Util.customConfirmObj.radioBtn.bindData(config.radioData);
            Util.customConfirmObj.autoSelect(config.radioData);
        }
    }
    Util.customConfirmObj.show();
};
//Util.customConfirm();

Util.qsFullMarsk = function(){
    this.html = "<div class='window-body-full-marsk'></div>";
    this.obj = null;
    this.init();
};
Util.qsFullMarsk.prototype = {
    init: function(){
        this.obj = $(this.html);
        this.obj.appendTo(document.body);
        this.hide();
    },
    show: function(){
        this.obj.show();
    },
    hide: function(){
        this.obj.hide();
    }
};
var QS_FullMarsk = new Util.qsFullMarsk();